'''
$Revision: 109 $
$LastChangedDate: 2008-12-23 13:45:55 +0000 (Tue, 23 Dec 2008) $
Some basic unittesting
Really need to expand this.
'''
import unittest

from MomentClosure.GlobalVariables import globalVariables
from MomentClosure.GetReactionInformation import ReactionInformation
from MomentClosure.VariableDict import Variables

class TestClosure(unittest.TestCase):
    '''Tests the factorial, binomial and pow functions'''
    
    def setUp(self):
        r = ReactionInformation()
        r.setSpeciesOrder(['A','B','C','D'])


    def testNormalApproximation_1(self):
        self.__testNormalApproximation_1(1)
        self.__testNormalApproximation_1(2)        
        self.__testNormalApproximation_1(3)
              
        
        
    def __testNormalApproximation_1(self, order):
         
        Variables().initialise()
        globalVariables(closure_order =order)
        mu1 = Variables().getMoment((1,))
        mu2 = Variables().getMoment((2,))
        mu3 = Variables().getMoment((3,))
        mu4 = Variables().getMoment((4,))   
 
        if order <= 1:
            self.assertEqual(mu2,mu1**2)
            self.assertEqual(mu3,mu1**3)
            self.assertEqual(mu4,mu1**4)

        if order <= 2:
            self.assertEqual(mu3,-2*mu1**3+3*mu2*mu1)
            self.assertEqual(mu4,-2*mu1**4+3*mu2**2)

        if order <= 3:
            diff = mu4 - (6*mu1**4+4*mu3*mu1-12*mu2*mu1**2+3*mu2**2)
            self.assertEqual(diff.expand(), 0)


    def testNormalApproximation_2(self):
        self.__testNormalApproximation_2(1)
        self.__testNormalApproximation_2(2)        
        self.__testNormalApproximation_2(3)        
        
        
    def __testNormalApproximation_2(self, order):
         
        Variables().initialise()
        globalVariables(closure_order =order)
        mu10 = Variables().getMoment((1,0))
        mu01 = Variables().getMoment((0,1))
        mu11 = Variables().getMoment((1,1))
        mu20 = Variables().getMoment((2,0))
        mu21 = Variables().getMoment((2,1))
        mu30 = Variables().getMoment((3,0))
        mu40 = Variables().getMoment((4,0))        
        
        if order <= 1:
            self.assertEqual(mu11,mu10*mu01)
            self.assertEqual(mu20,mu10**2)
            self.assertEqual(mu21,mu20*mu01+2*mu10*mu11-2*mu10**2*mu01)
            self.assertEqual(mu30,mu10**3)
            self.assertEqual(mu40,mu10**4)
        
        if order <= 2:
            self.assertEqual(mu21,mu20*mu01+2*mu10*mu11-2*mu10**2*mu01)
            self.assertEqual(mu30,-2*mu10**3+3*mu20*mu10)
            self.assertEqual(mu40,-2*mu10**4+3*mu20**2)

        if order <= 3:
            diff = mu40 - (6*mu10**4+4*mu30*mu10-12*mu20*mu10**2+3*mu20**2)
            self.assertEqual(diff.expand(),0)

    def testNormalApproximation_3(self):
        self.__testNormalApproximation_3(1)
        self.__testNormalApproximation_3(2)        
        self.__testNormalApproximation_3(3)        
        
        
    def __testNormalApproximation_3(self, order):
         
        Variables().initialise()
   
        globalVariables(closure_order =order)
        mu100 = Variables().getMoment((1,0,0))
        mu010 = Variables().getMoment((0,1,0))
        mu001 = Variables().getMoment((0,0,1))

        mu200 = Variables().getMoment((2,0,0))
        mu110 = Variables().getMoment((1,1,0))
        mu011 = Variables().getMoment((0,1,1))
        mu101 = Variables().getMoment((1,0,1))
        mu020 = Variables().getMoment((0,2,0))
        mu011 = Variables().getMoment((0,1,1))
        mu002 = Variables().getMoment((0,0,2))
        
        mu300 = Variables().getMoment((3,0,0))
        mu210 = Variables().getMoment((2,1,0))
        mu201 = Variables().getMoment((2,0,1))        
        mu120 = Variables().getMoment((1,2,0))
        mu102 = Variables().getMoment((1,0,2))
        mu012 = Variables().getMoment((0,1,2))        
        mu111 = Variables().getMoment((1,1,1))                
        mu030 = Variables().getMoment((0,3,0))                
        mu003 = Variables().getMoment((0,0,3))
        
        mu211 = Variables().getMoment((2,1,1))                                

        
        if order == 1:
            self.assertEqual(mu110,mu010*mu100)
        
        if order <= 2:
            self.assertEqual(mu300,-2*mu100**3+3*mu200*mu100)
            self.assertEqual(mu210,mu200*mu010+2*mu100*mu110-2*mu100**2*mu010)
            self.assertEqual(mu201,mu200*mu001+2*mu100*mu101-2*mu100**2*mu001)            
            self.assertEqual(mu012,mu002*mu010+2*mu001*mu011-2*mu001**2*mu010)        
            self.assertEqual(mu111,mu110*mu001+mu101*mu010-2*mu100*mu010*mu001+mu100*mu011)

        if order <= 3:
            exact = mu210*mu001+mu201*mu010-2*mu200*mu010*mu001+mu200*mu011\
                +2*mu101*mu110-4*mu100*mu110*mu001+2*mu100*mu111-4*mu100*mu010*mu101\
                +6*mu100**2*mu010*mu001-2*mu100**2*mu011
            diff = mu211 - exact
            self.assertEqual(diff.expand(), 0)



    
if __name__ == '__main__':
    unittest.main()


